#include "code_peephole.h"
#include<vector>
#include<string>
#include <variant> 

namespace code{
    void peephole_optimizer::peephole_optimize(Code& code){
        for(auto& func : code.funcs){
            for(auto& block : func.blocks){
                std::vector<Instruction>& instrs = block.instrs;
                size_t i = 0;
                while(i < instrs.size()){

                    if(i+1 < instrs.size() && instrs[i].op == OP_SW && instrs[i+1].op == OP_LW){
                        Operand& sw_rs1 = instrs[i].operands[0];
                        Operand& sw_offset = instrs[i].operands[1];
                        Operand& sw_rs2 = instrs[i].operands[2];
                        Operand& lw_rd = instrs[i+1].operands[0];
                        Operand& lw_offset = instrs[i+1].operands[1];
                        Operand& lw_rs2 = instrs[i+1].operands[2];
                        if(sw_offset == lw_offset && sw_rs2 == lw_rs2){
                            if(std::holds_alternative<std::string>(sw_rs1) && std::holds_alternative<std::string>(lw_rd)){
                                std::string sw_rs1_str = std::get<std::string>(sw_rs1);
                                std::string lw_rd_str = std::get<std::string>(lw_rd);
                                //对同一个寄存器操作：删除load指令
                                if(sw_rs1_str == lw_rd_str){
                                    instrs.erase(instrs.begin() + i + 1);
                                    continue;
                                }
                                else{//对不同寄存器操作：用addi 代替 load指令
                                    Instruction addi_instr;
                                    addi_instr.op = OP_ADDI;
                                    addi_instr.operands = { lw_rd, sw_rs1, 0 };
                                    instrs[i+1] = addi_instr;
                                    continue;
                                }
                            }
                        }
                    }
                    i++;
                }
            }
        }
    }
}